﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using SourceCodeIoc.Attributes;
using SourceCodeIoc.Aop;

namespace SourceCodeIoc.Factory
{
    /// <summary>
    /// 创建一个IOC工厂(目的：创建对象)
    /// List
    /// Set
    /// 字典
    /// 1  2  3
    /// 默认选择：字典 
    /// 
    /// </summary>

    public class DefaultFactory : AbstractIOCFactory
    {
        /// <summary>
        /// ioc容器
        /// </summary>
        public Dictionary<string, object> iocContainer = new Dictionary<string, object>();
        /// <summary>
        /// 临时ioc容器
        /// </summary>
        public Dictionary<string, object> iocTmpContainer = new Dictionary<string, object>();
        /// <summary>
        /// ioc type容器
        /// </summary>
        public Dictionary<string, Type> iocTypeContainer = new Dictionary<string, Type>();

        public int ScopeFlag = 0; // 关闭状态

        /// <summary>
        /// IOC Scope容器
        /// </summary>
        public Dictionary<string, object> iocScopeContainer = new Dictionary<string, object>();

        /// <summary>
        /// 目标1：创建对象，
        /// 目标2：存储对象，
        /// 目标3：依赖注入，属性赋值。
        /// 目标4：循环依赖。
        /// 目标5：依赖注入性能问题
        /// 目标6：类型过滤
        /// 目标7：类型属性过滤
        /// 目标8：AOP实现
        /// 目标8：AOP类型过滤
        /// 目标9：单例生命周期实现。
        /// 循环依赖使用前提：单例。
        /// 目标10：创建对象性能问题。按需创建
        /// 目标11：瞬时的，Trainsent。每次都重新创建
        /// 目标12：Scope生命周期 固定范围类生命周期。作用域
        /// 基本IOC容器。
        /// </summary>
        public DefaultFactory()
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            Type[] types = assembly.GetTypes();
            foreach (var type in types)
            {
                //iocTypeContainer.Add(type.FullName, type);
                IOCService iOCService = type.GetCustomAttribute<IOCService>();
                if (iOCService != null)
                {
                    iocTypeContainer.Add(type.FullName, type);
                }
            }

            foreach (var type in types)
            {
                //// 类型过滤
                //IOCService iOCService = type.GetCustomAttribute<IOCService>();
                //if (iOCService != null)
                //{
                //    //1、创建对象(Student--->Teacher)
                //    //递归创建对象 添加临时容器判断
                //    object _object = CreateObject(type);

                //    // 1.2 AOP过滤
                //    AOP aOP = type.GetCustomAttribute<AOP>();
                //    if (aOP != null)
                //    {
                //        // 1.2 使用动态代理创建 _object代理对象
                //        _object = AOPProxyGenerator.CreateAOPProxy(_object);
                //    }

                //    // key  要求：1、必须唯一 2、必须好记
                //    // 1、全限定名：命名空间+类名
                //    //    Guid：12312312qeqewasdq12
                //    //    雪花算法：1313123131313
                //    iocContainer.Add(type.FullName, _object);
                //}

                //// 1.1、对象属性赋值(依赖注入)
                //// 应采用递归创建对象
                //object xx = Activator.CreateInstance(type);
                //PropertyInfo[] propertyInfos = type.GetProperties();
                //foreach (var property in propertyInfos)
                //{
                //    //foreach (var type1 in types)
                //    //{

                //    //    if (property.PropertyType.Equals(type1))
                //    //    {
                //    //        // Teacher--->School
                //    //        object _objectvalue = Activator.CreateInstance(type1);

                //    //        PropertyInfo[] propertyInfos1 = type1.GetProperties();
                //    //        foreach (var property1 in propertyInfos1)
                //    //        {
                //    //            foreach (var type2 in types)
                //    //            {
                //    //                if (property1.PropertyType.Equals(type2))
                //    //                {
                //    //                    // School
                //    //                    object _objectvalue1 = Activator.CreateInstance(type2);

                //    //                    property.SetValue(_objectvalue, _objectvalue1);
                //    //                }
                //    //            }
                //    //        }
                //    //        property.SetValue(xx, _objectvalue);
                //    //    }
                //    //}

                //    Type type3 = types.Where(x => x.FullName == property.PropertyType.FullName).FirstOrDefault();
                //    if (type3 != null)
                //    {
                //        // Teacher--->School
                //        object _objectvalue = Activator.CreateInstance(type3);

                //        PropertyInfo[] propertyInfos1 = type3.GetProperties();
                //        foreach (var property1 in propertyInfos1)
                //        {
                //            Type type4 = types.Where(x => x.FullName == property1.PropertyType.FullName).FirstOrDefault();
                //            if (type4 != null)
                //            {
                //                object _objectvalue1 = Activator.CreateInstance(type4);
                //                property1.SetValue(_objectvalue, _objectvalue1);
                //            }
                //        }
                //        property.SetValue(xx, _objectvalue);
                //    }
                //}
            }
        }

        /// <summary>
        /// 1、自己调用自己
        /// 步骤
        /// 1、从逻辑代码中找到，通用的逻辑代码
        /// 2、从通用的逻辑代码中，找到通用的参数
        /// 3、自定调用自己。
        /// 
        /// 缺陷1：依赖注入：无限嵌套对象依赖问题。
        /// 无限递归：循环依赖。栈内存溢出。
        /// Student  Teacher  Student
        /// 如果对象创建了，还需要创建吗，不需要了。
        /// 容器：没有的。递归没有执行完
        /// 方案：零时IOC容器。用来存储递归创建对象的。无法使用。
        /// 缺陷2：性能问题。属性赋值存在性能问题。
        /// 10000 10000
        /// 1 10000次  浪费9999次
        /// 10000 * 9999 = 9999万次。时间非常长,10多分钟
        /// 如何提升属性赋值的性能？
        /// 方案：空间换时间。字典空间换取for循环时间
        /// 工具：用Type字典。
        /// </summary>
        public object CreateObject(Type type)
        {
            // 1、判断临时容器是否存在对象
            if (iocTmpContainer.ContainsKey(type.FullName))
            {
                return iocTmpContainer[type.FullName];
            }

            // 1.1、创建对象  公司A  type.Assembly 公司B Activator
            //      1、type.Assembly
            //      2、Activator
            //object _object = Activator.CreateInstance(type);

            object _object = objectCreateStrategy.CreateObject(type); //策略模式

            //object _object = _objectCreateStrategy.CreateObject(type);

            // 2、存储临时对象
            iocTmpContainer.Add(type.FullName, _object);

            PropertyInfo[] propertyInfos = type.GetProperties();
            foreach (var property in propertyInfos)
            {
                /*foreach (var type1 in types)
                {
                    if (property.PropertyType.Equals(type1))
                    {*/
                IOCInject iOCInject = property.GetCustomAttribute<IOCInject>();
                if (iOCInject != null)
                {
                    Type type1 = iocTypeContainer[property.PropertyType.FullName];
                    // School
                    object _objectvalue = CreateObject(type1);
                    property.SetValue(_object, _objectvalue);
                }
                /*  }
              }*/
            }
            return _object;
        }

        public override object GetObject(string FullName) 
        {
            Type type = iocTypeContainer[FullName];
            // 1.1、获取自定义特性
            IOCService iOCService = type.GetCustomAttribute<IOCService>();
            if (iOCService != null)
            {
                // 1.2、获取生命周期类型
                if (iOCService._serviceLifetime == "Trainsent")
                {
                    object _object = CreateObject(type);

                    // 2 AOP过滤
                    AOP aOP = type.GetCustomAttribute<AOP>();
                    if (aOP != null)
                    {
                        // 1.2 使用动态代理创建 _object代理对象
                        _object = AOPProxyGenerator.CreateAOPProxy(_object);
                    }
                    return _object;
                }
                else if (iOCService._serviceLifetime == "Scope" && ScopeFlag == 1)
                {
                    // 对象是否已经创建
                    if (iocScopeContainer.ContainsKey(FullName))
                    {
                        return iocScopeContainer[FullName];
                    }

                    object _object = CreateObject(type);

                    // 2 AOP过滤
                    AOP aOP = type.GetCustomAttribute<AOP>();
                    if (aOP != null)
                    {
                        // 1.2 使用动态代理创建 _object代理对象
                        _object = AOPProxyGenerator.CreateAOPProxy(_object);
                    }

                    // 3、存储对象
                    iocScopeContainer.Add(type.FullName, _object);

                    // 4、返回对象
                    return iocScopeContainer[FullName];
                }
                else if (iOCService._serviceLifetime == "Singlaton")
                {
                    // 对象是否已经创建
                    if (iocContainer.ContainsKey(FullName))
                    {
                        return iocContainer[FullName];
                    }

                    object _object = CreateObject(type);

                    // 2 AOP过滤
                    AOP aOP = type.GetCustomAttribute<AOP>();
                    if (aOP != null)
                    {
                        // 1.2 使用动态代理创建 _object代理对象
                        _object = AOPProxyGenerator.CreateAOPProxy(_object);
                    }

                    // 3、存储对象
                    iocContainer.Add(type.FullName, _object);

                    // 4、返回对象
                    return iocContainer[FullName];
                }
            }
            return null;
        }

        public override void StartScope()
        {
            ScopeFlag = 1;
        }

        public override void StopScope()
        {
            ScopeFlag = 0;
            iocScopeContainer.Clear();
        }
    }
}
